#include <unistd.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <string.h>

#include "rtp.h"
#include "rtsp.h"

RtpEmitter::RtpEmitter(uint16_t self_port, const char *target_ip, uint16_t target_port, uint8_t ptype)
{
    _socket = socket(PF_INET, SOCK_DGRAM, 0);
    // 绑定自己的ip和端口
    sockaddr_in server_adr;
    memset(&server_adr, 0, sizeof(server_adr));
    server_adr.sin_family = AF_INET;
    server_adr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_adr.sin_port = htons(self_port);
    bind(_socket, (sockaddr *)&server_adr, sizeof(server_adr));

    // 初始化客户端的ip和端口
    memset(&_target_adr, 0, sizeof(_target_adr));
    _target_adr.sin_family = AF_INET;
    _target_adr.sin_addr.s_addr = inet_addr(target_ip);
    _target_adr.sin_port = htons(target_port);

    // 初始化rtp头部
    _rtpheader.version = 2;
    _rtpheader.padding = 0;
    _rtpheader.extension = 0;
    _rtpheader.csrc_num = 0;
    _rtpheader.marker = 0;
    _rtpheader.payload_type = ptype;
    _rtpheader.sequence = 0;
    _rtpheader.timestamp = 0;
    _rtpheader.ssrc = 0x12345678;

    // size_t len = sizeof(_rtpheader);
    // uint8_t *tt = (uint8_t *)&_rtpheader;
    // uint8_t byte1 = tt[0];
    // uint8_t byte2 = tt[1];
    // uint8_t byte3 = tt[2];
    // uint8_t byte4 = tt[3];

    // int abc = byte1 + byte4;
}

RtpEmitter::~RtpEmitter()
{
}

void RtpEmitter::send_nalu(const char *nalu, size_t nalu_len, bool islast)
{
    if (nalu_len == 0)
        return;

    // 判断nalu类型
    uint8_t nalu_head;
    memcpy(&nalu_head, nalu, 1);
    uint8_t ntype = nalu_head & 0b00011111;

    size_t rtpheader_len = sizeof(_rtpheader);

    if (nalu_len <= 1400)
    {
        _rtpheader.marker = islast ? 1 : 0;
        _rtpheader.sequence = htons(_rtpheader.sequence);
        _rtpheader.timestamp = htonl(_rtpheader.timestamp);

        char *data = new char[rtpheader_len + nalu_len];
        memcpy(data, &_rtpheader, rtpheader_len);
        memcpy(data + rtpheader_len, nalu, nalu_len);

        ssize_t rst = sendto(_socket, data, rtpheader_len + nalu_len, 0,
                             (sockaddr *)&_target_adr, sizeof(_target_adr));

        _rtpheader.sequence = ntohs(_rtpheader.sequence);
        _rtpheader.timestamp = ntohl(_rtpheader.timestamp);
        _rtpheader.sequence++;

        if(data)
        {
            delete[] data;
        }
    }
    else
    {
        size_t packet_num = (nalu_len - 1) / 1400 + 1;
        uint8_t fu_indicator = (nalu_head & 0b11100000) + 28;

        for (int i = 0; i < packet_num; i++)
        {
            uint8_t fu_header;
            if (i == 0)
            {
                _rtpheader.marker = 0;
                _rtpheader.sequence = htons(_rtpheader.sequence);
                _rtpheader.timestamp = htonl(_rtpheader.timestamp);
                fu_header = 0b10000000 + ntype;

                char *data = new char[rtpheader_len + 1400 + 2];
                memcpy(data, &_rtpheader, rtpheader_len);
                memcpy(data + rtpheader_len, &fu_indicator, 1);
                memcpy(data + rtpheader_len + 1, &fu_header, 1);
                memcpy(data + rtpheader_len + 2, nalu + 1, 1400);

                ssize_t rst = sendto(_socket, data, rtpheader_len + 1400 + 2, 0,
                                     (sockaddr *)&_target_adr, sizeof(_target_adr));

                _rtpheader.sequence = ntohs(_rtpheader.sequence);
                _rtpheader.timestamp = ntohl(_rtpheader.timestamp);
                _rtpheader.sequence++;

                if (data)
                {
                    delete[] data;
                }
            }
            else if (i < packet_num - 1)
            {
                _rtpheader.marker = 0;
                _rtpheader.sequence = htons(_rtpheader.sequence);
                _rtpheader.timestamp = htonl(_rtpheader.timestamp);
                fu_header = ntype;

                char *data = new char[rtpheader_len + 1400 + 2];
                memcpy(data, &_rtpheader, rtpheader_len);
                memcpy(data + rtpheader_len, &fu_indicator, 1);
                memcpy(data + rtpheader_len + 1, &fu_header, 1);
                memcpy(data + rtpheader_len + 2, nalu + 1 + 1400 * i, 1400);

                ssize_t rst = sendto(_socket, data, rtpheader_len + 1400 + 2, 0,
                                     (sockaddr *)&_target_adr, sizeof(_target_adr));

                _rtpheader.sequence = ntohs(_rtpheader.sequence);
                _rtpheader.timestamp = ntohl(_rtpheader.timestamp);
                _rtpheader.sequence++;

                if (data)
                {
                    delete[] data;
                }
            }
            else if (i == packet_num - 1)
            {
                _rtpheader.marker = 1;
                _rtpheader.sequence = htons(_rtpheader.sequence);
                _rtpheader.timestamp = htonl(_rtpheader.timestamp);
                fu_header = 0b01000000 + ntype;

                size_t last_len = nalu_len - 1 - 1400 * i;
                char *data = new char[rtpheader_len + 2 + last_len];
                memcpy(data, &_rtpheader, rtpheader_len);
                memcpy(data + rtpheader_len, &fu_indicator, 1);
                memcpy(data + rtpheader_len + 1, &fu_header, 1);
                memcpy(data + rtpheader_len + 2, nalu + 1 + 1400 * i, last_len);

                ssize_t rst = sendto(_socket, data, rtpheader_len + 2 + last_len, 0,
                                     (sockaddr *)&_target_adr, sizeof(_target_adr));

                _rtpheader.sequence = ntohs(_rtpheader.sequence);
                _rtpheader.timestamp = ntohl(_rtpheader.timestamp);
                _rtpheader.sequence++;

                if (data)
                {
                    delete[] data;
                }
            }
        }
    }

    if (ntype < 6) // 仅为VCL型NAL时，增加时间戳
    {
        _rtpheader.timestamp += 90000 / 60;
    }
    // if(ntype == 1 || ntype == 5)
    // {
        
    // }
}

void RtpEmitter::send_adts(const char *adts_raw, size_t len, bool islast)
{
    size_t rtpheader_len = sizeof(_rtpheader);
    uint16_t frame_size = len;

    _rtpheader.marker = islast ? 1 : 0;
    _rtpheader.sequence = htons(_rtpheader.sequence);
    _rtpheader.timestamp = htonl(_rtpheader.timestamp);

    uint8_t payload[4];
    payload[0] = 0x00;
    payload[1] = 0x10;
    uint8_t t1 = payload[2] = (frame_size & 0x1FE0) >> 5;
    uint8_t t2 = payload[3] = (frame_size & 0x001F) << 3;

    char *data = new char[rtpheader_len + 4 + len];
    memcpy(data, &_rtpheader, rtpheader_len);
    memcpy(data + rtpheader_len, payload, 4);
    memcpy(data + rtpheader_len + 4, adts_raw, frame_size);

    ssize_t rst = sendto(_socket, data, rtpheader_len + 4 + len, 0,
                         (sockaddr *)&_target_adr, sizeof(_target_adr));

    _rtpheader.sequence = ntohs(_rtpheader.sequence);
    _rtpheader.timestamp = ntohl(_rtpheader.timestamp);
    _rtpheader.sequence++;

    if (data)
    {
        delete[] data;
    }

    _rtpheader.timestamp += 1025;
}
